#include "swinganimationeffect.h"
#include "deviceactor.h"
#include <osg\Node>

namespace VrDataCore
{
	SwingAnimationEffectUpdateCallback::SwingAnimationEffectUpdateCallback(SwingAnimationEffect* un)
	{
		_un = un ;
	}

	void SwingAnimationEffectUpdateCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
	{
		if( !_un )
		{
			traverse(node,nv);
			return;
		}
		_un->update();
		//if(_nestedCallback.valid())
		//	 (*_nestedCallback)(node,nv);
		traverse(node,nv);
	}

	SwingAnimationEffect::SwingAnimationEffect(int swing):_startToEnd(false),_setupCallback(false),_update(false)
	{
		_updateCallback = new SwingAnimationEffectUpdateCallback(this);
	}

	SwingAnimationEffect::~SwingAnimationEffect()
	{}

	void SwingAnimationEffect::setMaxDistance(osg::Vec3 dis)
	{
		_maxDistance = dis;
	}

	osg::Vec3 SwingAnimationEffect::getMaxDistance()
	{
		return _maxDistance;
	}

	void SwingAnimationEffect::setAnimationTime(float time)
	{
		_totalTime = time;
	}

	float SwingAnimationEffect::getAnimationTime()
	{
		return _totalTime;
	}

	void SwingAnimationEffect::startToEnd()
	{
		if(!_transform.valid() || _transform.valid() && _transform->getPosition()!=_maxDistance)
		{
			_startToEnd = true;
			if(_bindingMeshDrawableActor!=NULL)
				apply(_bindingMeshDrawableActor);
		}
	}

	void SwingAnimationEffect::endToStart()
	{
		if(!_transform.valid() || _transform.valid() && _transform->getPosition()!=osg::Vec3(0.0f,0.0f,0.0f))
		{
			_startToEnd = false;
			if(_bindingMeshDrawableActor!=NULL)
				apply(_bindingMeshDrawableActor);
		}
	}

	void SwingAnimationEffect::update()
	{
		if(_update)
		{
			osg::Timer_t nowtime = osg::Timer::instance()->delta_m(_startTick,osg::Timer::instance()->tick());
			float p = nowtime/_totalTime;
			if(p>1)
			{
				osg::Vec3 endpos;
				if(_startToEnd)
					endpos = _startToEnd?_maxDistance:osg::Vec3(0.0f,0.0f,0.0f);
				_transform->setPosition(endpos);
				_update = false;
			}
			else
			{
				osg::Vec3 pos = _transform->getPosition();
				osg::Vec3 endpos = _startToEnd?_maxDistance:osg::Vec3(0.0f,0.0f,0.0f);
				pos = pos + (endpos - pos)*p;
				_transform->setPosition(pos);
			}
		}
	}

	void SwingAnimationEffect::apply(CoreBase::ActorBase* actor)
	{
		_bindingMeshDrawableActor = actor;
		if(!_setupCallback)
		{
			if(!_transform.valid())
				_transform = new osg::PositionAttitudeTransform;
			osg::Group* parent = actor->getDrawable()->getOSGNode()->asGroup();
			for(unsigned int i=0;i<parent->getNumChildren();++i)
			{
				_transform->addChild(parent->getChild(i));
			}
			parent->removeChildren(0,parent->getNumChildren());
			parent->addChild(_transform);
			_transform->addUpdateCallback(_updateCallback);
			_setupCallback = true;
		}
		_startTick = osg::Timer::instance()->tick();
		_update = true;
	}

	void SwingAnimationEffect::unApply(CoreBase::ActorBase* actor)
	{
		_update = false;
		_setupCallback = false;
		if(_transform.valid())
		{
			_transform->removeUpdateCallback(_updateCallback);
			osg::Group* parent = _bindingMeshDrawableActor->getDrawable()->getOSGNode()->asGroup();
			parent->removeChild(_transform);
			for(unsigned int i=0;i<_transform->getNumChildren();++i)
			{
				parent->addChild(_transform->getChild(i));
			}
			_transform->removeChildren(0,_transform->getNumChildren());
		}
	}
}